package com.finalterm.product.service.impl;

import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.finalterm.common.exception.BusinessException;
import com.finalterm.common.result.Result;
import com.finalterm.product.dto.ProductCreateDTO;
import com.finalterm.product.dto.StockDeductDTO;
import com.finalterm.product.entity.Product;
import com.finalterm.product.entity.StockRecord;
import com.finalterm.product.feign.UserServiceClient;
import com.finalterm.product.mapper.ProductMapper;
import com.finalterm.product.mapper.StockRecordMapper;
import com.finalterm.product.service.ProductCacheService;
import com.finalterm.product.service.ProductService;
import com.finalterm.product.vo.ProductVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品服务实现类
 */
@Slf4j
@Service
@RefreshScope
@RequiredArgsConstructor
public class ProductServiceImpl implements ProductService {

    private final ProductMapper productMapper;
    private final StockRecordMapper stockRecordMapper;
    private final UserServiceClient userServiceClient;
    private final ProductCacheService productCacheService;

    @Value("${product.cache.time:60}")
    private int cacheTime;
    
    @Override
    public ProductVO createProduct(ProductCreateDTO createDTO) {
        Product product = new Product();
        BeanUtils.copyProperties(createDTO, product);
        product.setStatus(1);
        product.setCreateTime(LocalDateTime.now());
        product.setUpdateTime(LocalDateTime.now());
        
        productMapper.insert(product);
        
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(product, productVO);
        
        log.info("商品创建成功：{}", product.getName());
        return productVO;
    }
    
    @Override
    public ProductVO getProductDetail(Long productId, Long userId) {
        // 验证用户有效性（带Sentinel熔断保护）
        if (userId != null) {
            Boolean b = validateUserWithCircuitBreaker(userId);
            if (!b) {
                return productCacheService.getDefaultProduct(1L);
            }
        }
        // 从数据库获取商品信息
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }

        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(product, productVO);
        return productVO;
    }

    /**
     * 用户验证
     */
    private Boolean validateUserWithCircuitBreaker(Long userId) {
        // 模拟user-service超时接口，触发熔断降级
        Result<Boolean> result = userServiceClient.validateUserSlow(userId);
        // 正常接口
        // Result<Boolean> result = userServiceClient.validateUser(userId);
        if (result.getMessage().equals("系统熔断机制触发，接口超时，用户验证失败")) {
            log.warn("用户验证失败，触发熔断，返回商品缓存userId: {}", userId);
            return false;
        } else {
            log.debug("用户验证成功，userId: {}", userId);
            return true;
        }
    }
    
    @Override
    public Page<ProductVO> getProductList(int page, int size, String category) {
        Page<Product> productPage = new Page<>(page, size);
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Product::getStatus, 1);
        
        if (StringUtils.hasText(category)) {
            wrapper.eq(Product::getCategory, category);
        }
        
        wrapper.orderByDesc(Product::getCreateTime);
        
        Page<Product> result = productMapper.selectPage(productPage, wrapper);
        
        // 转换为VO
        Page<ProductVO> voPage = new Page<>();
        BeanUtils.copyProperties(result, voPage);
        
        List<ProductVO> voList = result.getRecords().stream().map(product -> {
            ProductVO vo = new ProductVO();
            BeanUtils.copyProperties(product, vo);
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        return voPage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deductStock(StockDeductDTO deductDTO) {
        // 检查是否已经处理过该订单（幂等性）
        LambdaQueryWrapper<StockRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockRecord::getOrderId, deductDTO.getOrderId())
               .eq(StockRecord::getOperationType, "DEDUCT");
        StockRecord existRecord = stockRecordMapper.selectOne(wrapper);
        
        if (existRecord != null) {
            log.info("订单{}已处理过库存扣减，跳过", deductDTO.getOrderId());
            return true;
        }
        
        // 获取当前库存
        Product product = productMapper.selectById(deductDTO.getProductId());
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        if (product.getStock() < deductDTO.getQuantity()) {
            throw new BusinessException("库存不足");
        }
        
        // 扣减库存
        int affected = productMapper.deductStock(deductDTO.getProductId(), deductDTO.getQuantity());
        if (affected == 0) {
            throw new BusinessException("库存扣减失败");
        }
        
        // 记录库存操作
        StockRecord record = new StockRecord();
        record.setProductId(deductDTO.getProductId());
        record.setOrderId(deductDTO.getOrderId());
        record.setOperationType("DEDUCT");
        record.setQuantity(deductDTO.getQuantity());
        record.setBeforeStock(product.getStock());
        record.setAfterStock(product.getStock() - deductDTO.getQuantity());
        record.setCreateTime(LocalDateTime.now());
        stockRecordMapper.insert(record);

        log.info("库存扣减成功，商品ID：{}，扣减数量：{}", deductDTO.getProductId(), deductDTO.getQuantity());
        return true;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recoverStock(Long productId, Integer quantity, String orderId) {
        // 检查是否已经处理过该订单的库存恢复（幂等性）
        LambdaQueryWrapper<StockRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockRecord::getOrderId, orderId)
               .eq(StockRecord::getOperationType, "RECOVER");
        StockRecord existRecord = stockRecordMapper.selectOne(wrapper);
        
        if (existRecord != null) {
            log.info("订单{}已处理过库存恢复，跳过", orderId);
            return true;
        }
        
        // 获取当前库存
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        // 恢复库存
        int affected = productMapper.recoverStock(productId, quantity);
        if (affected == 0) {
            throw new BusinessException("库存恢复失败");
        }
        
        // 记录库存操作
        StockRecord record = new StockRecord();
        record.setProductId(productId);
        record.setOrderId(orderId);
        record.setOperationType("RECOVER");
        record.setQuantity(quantity);
        record.setBeforeStock(product.getStock());
        record.setAfterStock(product.getStock() + quantity);
        record.setCreateTime(LocalDateTime.now());
        stockRecordMapper.insert(record);

        log.info("库存恢复成功，商品ID：{}，恢复数量：{}", productId, quantity);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmStockDeduction(String orderNo, Long productId, Integer quantity, String orderStatus) {
        log.info("开始确认库存扣减，订单号：{}，商品ID：{}，数量：{}，订单状态：{}",
                orderNo, productId, quantity, orderStatus);

        // 检查是否已经确认过该订单的库存扣减（幂等性）
        LambdaQueryWrapper<StockRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockRecord::getOrderId, orderNo)
               .eq(StockRecord::getOperationType, "CONFIRM");
        StockRecord existRecord = stockRecordMapper.selectOne(wrapper);

        if (existRecord != null) {
            log.info("订单{}已确认过库存扣减，跳过", orderNo);
            return true;
        }

        // 检查是否存在对应的库存扣减记录
        LambdaQueryWrapper<StockRecord> deductWrapper = new LambdaQueryWrapper<>();
        deductWrapper.eq(StockRecord::getOrderId, orderNo)
                    .eq(StockRecord::getOperationType, "DEDUCT");
        StockRecord deductRecord = stockRecordMapper.selectOne(deductWrapper);

        if (deductRecord == null) {
            log.warn("订单{}未找到库存扣减记录，无法确认", orderNo);
            return false;
        }

        // 验证库存扣减记录的商品ID和数量是否匹配
        if (!deductRecord.getProductId().equals(productId) || !deductRecord.getQuantity().equals(quantity)) {
            log.warn("订单{}库存扣减记录不匹配，记录商品ID：{}，数量：{}，请求商品ID：{}，数量：{}",
                    orderNo, deductRecord.getProductId(), deductRecord.getQuantity(), productId, quantity);
            return false;
        }

        // 获取当前商品信息
        Product product = productMapper.selectById(productId);
        if (product == null) {
            log.warn("商品不存在，商品ID：{}", productId);
            return false;
        }

        // 记录库存确认操作
        StockRecord confirmRecord = new StockRecord();
        confirmRecord.setProductId(productId);
        confirmRecord.setOrderId(orderNo);
        confirmRecord.setOperationType("CONFIRM");
        confirmRecord.setQuantity(quantity);
        confirmRecord.setBeforeStock(product.getStock());
        confirmRecord.setAfterStock(product.getStock()); // 确认操作不改变库存数量
        confirmRecord.setCreateTime(LocalDateTime.now());
        stockRecordMapper.insert(confirmRecord);

        log.info("库存扣减确认成功，订单号：{}，商品ID：{}，数量：{}", orderNo, productId, quantity);
        return true;
    }

    @Override
    public ProductVO updateProduct(Long productId, ProductCreateDTO updateDTO) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        BeanUtils.copyProperties(updateDTO, product);
        product.setUpdateTime(LocalDateTime.now());
        
        productMapper.updateById(product);

        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(product, productVO);

        log.info("商品更新成功：{}", product.getName());
        return productVO;
    }
    
    @Override
    public boolean deleteProduct(Long productId) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        // 软删除：设置状态为0
        product.setStatus(0);
        product.setUpdateTime(LocalDateTime.now());
        productMapper.updateById(product);

        log.info("商品删除成功：{}", product.getName());
        return true;
    }
}
